/*
 *   Copyright (c) 2008, Ueda Laboratory LMNtal Group <lmntal@ueda.info.waseda.ac.jp>
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions are
 *   met:
 *
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *
 *    3. Neither the name of the Ueda Laboratory LMNtal Group nor the
 *       names of its contributors may be used to endorse or promote
 *       products derived from this software without specific prior
 *       written permission.
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

package extgui.filedrop;

import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.TransferHandler;

import extgui.filedrop.event.FileDropListener;

/**
 * TransferHandler for file drop preserving copy/cut/paste actions.
 * @author Yuuki.S
 */
@SuppressWarnings("serial")
public class FileDropTransferHandler extends TransferHandler
{
	private TransferHandler defHandler;
	private List<FileDropListener> listeners = new ArrayList<FileDropListener>();

	public FileDropTransferHandler(TransferHandler defHandler)
	{
		this.defHandler = defHandler;
	}

	/**
	 * Add {@code listener} to receive files when dropped.
	 * If {@code listener == null}, {@code listener} is not added to the listener list of this instance.
	 * @param listener {@link FileDropListener} to be added
	 */
	public void addFileDropListener(FileDropListener listener)
	{
		if (listener != null)
		{
			listeners.add(listener);
		}
	}

	/**
	 * Remove {@code listener} from the listener list of this instance.
	 * If {@code listener} is not contained the list, the list will not change.
	 * @param listener {@ilnk FileDropListener} to be removed
	 */
	public void removeFileDropListener(FileDropListener listener)
	{
		listeners.remove(listener);
	}

	public int getSourceActions(JComponent c)
	{
		return defHandler.getSourceActions(c);
	}

	public void exportToClipboard(JComponent comp, Clipboard clip, int action)
	{
		defHandler.exportToClipboard(comp, clip, action);
	}

	public boolean canImport(TransferHandler.TransferSupport s)
	{
		return canImportDerived(s) || defHandler.canImport(s);
	}

	public boolean importData(TransferHandler.TransferSupport support)
	{
		if (canImport(support) && support.isDrop())
		{
			Transferable t = support.getTransferable();
			if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
			{
				try
				{
					@SuppressWarnings("unchecked")
					List<File> files = (List<File>)t.getTransferData(DataFlavor.javaFileListFlavor);
					dispatchFileDropEvent(files);
					return true;
				}
				catch (UnsupportedFlavorException e)
				{
					e.printStackTrace();
				}
				catch (IOException e)
				{
					e.printStackTrace();
				}
			}
		}
		return defHandler.importData(support);
	}

	private boolean canImportDerived(TransferHandler.TransferSupport s)
	{
		return s.isDrop() && s.isDataFlavorSupported(DataFlavor.javaFileListFlavor);
	}

	private void dispatchFileDropEvent(List<File> files)
	{
		for (FileDropListener l : listeners)
		{
			l.filesDropped(files);
		}
	}
}
